package com.ywb.ex07;

import java.awt.BorderLayout;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.*;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class Task1And2Server extends JFrame {
    private JTextArea ta_info;
//    服务器socket对象
    private ServerSocket server;
//    客户端socket对象
    private Socket socket;
    private ExecutorService exec;
    private Hashtable<String, Socket> map = new Hashtable<String, Socket>();//



    public static void main(String args[]) {
        Task1And2Server frame = new Task1And2Server();
        frame.setVisible(true);
        // 调用方法创建套接字对象
        frame.createSocket();
    }
    /**
     * 建立套接字
     */
    public void createSocket(){
        try{
            server = new ServerSocket(2020);
            //手动创建线程池
            exec = new ThreadPoolExecutor(
                    5, 10, 60
                    , TimeUnit.MILLISECONDS
                    , new LinkedBlockingQueue<>(1024)
                    , new ThreadPoolExecutor.AbortPolicy());
            while(true){
                ta_info.append("等待新客户连接..." + "\n");
                socket = server.accept();
                exec.execute(new Thread(new ServerThread(socket)));
                ta_info.append("客户连接成功:" + socket + '\n');
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    class ServerThread implements Runnable{
        Socket socket;
        ServerThread(Socket s){
            socket = s;
        }
        @Override
        public void run() {
            try {
                ObjectInputStream ins = new ObjectInputStream(socket
                        .getInputStream());
                while (true) {
                    Vector v = null;
                    try {
                        v = (Vector) ins.readObject();
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                    if (v != null && v.size() > 0) {
                        for (int i = 0; i < v.size(); i++) {
                            String info = (String) v.get(i);// 读取信息
                            String key = "";
                            if (info.startsWith("用户：")) {// 添加登录用户到客户端列表
                                key = info.substring(3, info.length());// 获得用户名并作为键使用
                                map.put(key, socket);// 添加键值对
                                Set<String> set = map.keySet();// 获得集合中所有键的 Set 视图
                                Iterator<String> keyIt = set.iterator();// 获得所有键的迭代器
                                while (keyIt.hasNext()) {
                                    String receiveKey = keyIt.next();// 获得表示接收信息的键
                                    Socket s = map.get(receiveKey);// 获得与该键对应的套接字对象
                                    PrintWriter out = new PrintWriter(s
                                            .getOutputStream(), true);// 创建输出流对象
                                    Iterator<String> keyIt1 =
                                            set.iterator();// 获得所有键的迭代器
                                    while (keyIt1.hasNext()) {
                                        String receiveKey1 = keyIt1.next();//获得键，用于向客户端添加用户列表
                                        out.println(receiveKey1);// 发送信息
                                        out.flush();// 刷新输出缓冲区
                                    }
                                }
                            } else if (info.startsWith("退出：")) {key = info.substring(3);// 获得退出用户的键
                                map.remove(key);// 添加键值对
                                Set<String> set = map.keySet();// 获得集合中所有键的 Set 视图
                                Iterator<String> keyIt = set.iterator();// 获得所有键的迭代器
                                while (keyIt.hasNext()) {
                                    String receiveKey = keyIt.next();// 获得表示接收信息的键
                                    Socket s = map.get(receiveKey);// 获得与该键对应的套接字对象
                                    PrintWriter out = new PrintWriter(s
                                            .getOutputStream(), true);// 创建输出流对象
                                    out.println("退出：" + key);// 发送信息
                                    out.flush();// 刷新输出缓冲区
                                }
                            } else {// 转发接收的消息
                                key = info.substring(info.indexOf("：发送给：") + 5, info.indexOf("：的信息是："));// 获得接收方的 key 值,即接收方的用户名
                                String sendUser = info.substring(0, info.indexOf("：发送给："));// 获得发送方的 key 值,即发送方的用户名
                                Set<String> set = map.keySet();// 获得集合中所有键的 Set 视图
                                Iterator<String> keyIt = set.iterator();// 获得所有键的迭代器
                                while (keyIt.hasNext()) {
                                    String receiveKey = keyIt.next();// 获得表示接收信息的键
                                    if (key.equals(receiveKey)
                                            && !sendUser.equals(receiveKey)) {// 与接受用户相同，但不是发送用户
                                        Socket s = map.get(receiveKey);// 获得与该键对应的套接字对象
                                        PrintWriter out = new
                                                PrintWriter(s.getOutputStream(), true);// 创建输出流对象
                                        String Msg = "MSG" + info;
                                        ta_info.append(Msg + '\n');
                                        out.println(Msg);// 发送信息
                                        out.flush();// 刷新输出缓冲区
                                    }
                                }
                            }}
                    }
                }
            } catch (IOException e) {
                ta_info.append(socket + "已经退出。\n");
            }
        }
    }

    /**
     * 构造方法：创建服务器窗口
     */
    public Task1And2Server() {
        super();
        addWindowListener(new WindowAdapter() {
            public void windowIconified(final WindowEvent e) {
                setVisible(false);
            }
        });
        setTitle("聊天室服务器端");
        setBounds(100, 100, 385, 266);

        final JScrollPane scrollPane = new JScrollPane();
        getContentPane().add(scrollPane, BorderLayout.CENTER);

        ta_info = new JTextArea();
        scrollPane.setViewportView(ta_info);

//
    }

}


